package com.quiz.bis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.quiz.bis.constant.PaperStatus;
import com.quiz.bis.domain.bo.BisManualPaperBo;
import com.quiz.bis.domain.bo.BisPaperQuestionAddBo;
import com.quiz.bis.domain.model.BisPaperQuestions;
import com.quiz.bis.domain.model.BisPapers;
import com.quiz.bis.domain.model.BisQuestions;
import com.quiz.bis.domain.vo.BisPaperJsonVo;
import com.quiz.bis.domain.vo.BisPaperQuestionDetailVo;
import com.quiz.bis.domain.vo.BisPaperQuestionVo;
import com.quiz.bis.domain.vo.BisPapersDetailVo;
import com.quiz.bis.mapper.BisPaperMapper;
import com.quiz.bis.mapper.BisPaperQuestionMapper;
import com.quiz.bis.mapper.BisQuestionsMapper;
import com.quiz.bis.service.IBisPaperService;
import com.quiz.common.exception.ServiceException;
import com.quiz.common.mybatis.core.query.LambdaQueryWrapperPlus;
import com.quiz.common.mybatis.core.query.MPJLambdaWrapperPlus;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 试卷管理服务实现类
 * @author ahuan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BisPaperServiceImpl implements IBisPaperService {

    private final BisPaperMapper baseMapper;

    private final BisQuestionsMapper questionsMapper;

    private final BisPaperQuestionMapper paperQuestionMapper;

    /**
     * 手动组卷
     * @param bo
     * @return
     */
    @Override
    public Long manualPaper(BisManualPaperBo bo) {
        // 生成试卷草稿信息
        BisPapers draftPaper = new BisPapers();
        draftPaper.setPaperName(bo.getPaperName());
        draftPaper.setDescription(bo.getDescription());
        draftPaper.setTotalScore(bo.getTotalScore());
        draftPaper.setPassScore(bo.getPassScore());
        draftPaper.setStatus(PaperStatus.DRAFT);
        draftPaper.setQuestionSum(bo.getPaperQuestionBo().size());

        if(baseMapper.insert(draftPaper) <= 0){
            throw new ServiceException("试卷保存失败,请联系管理员!");
        }
        // 生成题目和试卷的关联信息
        List<BisPaperQuestions> paperQuesList = new ArrayList<>();
        for (BisPaperQuestionAddBo question : bo.getPaperQuestionBo()) {
            BisPaperQuestions paperQuestions = new BisPaperQuestions();
            paperQuestions.setPaperId(draftPaper.getPaperId());
            paperQuestions.setQuestionId(question.getQuestionId());
            paperQuestions.setQuestionOrder(question.getQuestionOrder());
            paperQuestions.setQuestionScore(question.getQuestionScore());
            paperQuesList.add(paperQuestions);
        }

        if(!paperQuestionMapper.insertBatch(paperQuesList)){
            throw new ServiceException("试卷题目信息保存失败,请联系管理员!");
        }

        return draftPaper.getPaperId();
    }

    /**
     * 获取试卷预览详情
     * @param paperId
     * @return
     */
    @Override
    public BisPapersDetailVo getPaperDetail(Long paperId) {
        MPJLambdaWrapper<BisPapers> wrapper = getPlusWrapper()
                .selectAll(BisPapers.class)
                .selectAll(BisPaperQuestions.class)
                .selectAll(BisQuestions.class)
                .selectCollection(BisPaperQuestionVo.class, BisPapers::getPaperQuestionList)
                .leftJoin(BisPaperQuestions.class, BisPaperQuestions::getPaperQuestionId, BisPapers::getPaperId)
                .leftJoin(BisQuestions.class, BisQuestions::getQuestionId, BisPaperQuestions::getQuestionId)
                .orderBy(true, false, BisPaperQuestions::getQuestionOrder)
                .eq(BisPapers::getPaperId, paperId);
        BisPaperQuestionDetailVo paperQuestionDetailVo = baseMapper.selectJoinOne(BisPaperQuestionDetailVo.class, wrapper);

        BisPapersDetailVo res = BeanUtil.copyProperties(paperQuestionDetailVo, BisPapersDetailVo.class);
        BisPaperJsonVo jsonVo = new BisPaperJsonVo();
        jsonVo.addQuestions(paperQuestionDetailVo.getPaperQuestionList());
        res.setJsonData(jsonVo);



        // 返回试卷id，供前端回调 <试卷预览详情> 接口
        return res;
    }

    /**
     * 获取试卷编辑详情
     * @param paperId
     * @return
     */
    @Override
    public BisPaperQuestionDetailVo getPaperEditDetail(Long paperId) {
        MPJLambdaWrapper<BisPapers> wrapper = getPlusWrapper()
                .selectAll(BisPapers.class)
                .selectAll(BisPaperQuestions.class)
                .selectAll(BisQuestions.class)
                .selectCollection(BisPaperQuestionVo.class, BisPapers::getPaperQuestionList)
                .leftJoin(BisPaperQuestions.class, BisPaperQuestions::getPaperQuestionId, BisPapers::getPaperId)
                .leftJoin(BisQuestions.class, BisQuestions::getQuestionId, BisPaperQuestions::getQuestionId)
                .orderBy(true, false, BisPaperQuestions::getQuestionOrder)
                .eq(BisPapers::getPaperId, paperId);
        return baseMapper.selectJoinOne(BisPaperQuestionDetailVo.class, wrapper);
    }


    /**
     * 编辑试卷
     * @param bo
     * @return
     */
    @Override
    @Transactional
    public Long editPaper(BisManualPaperBo bo) {
        // 生成试卷草稿信息
        BisPapers bisPapers = BeanUtil.copyProperties(bo, BisPapers.class);
        bisPapers.setQuestionSum(bo.getPaperQuestionBo().size());
        bisPapers.setStatus(PaperStatus.DRAFT);

        if(baseMapper.updateById(bisPapers) <= 0){
            throw new ServiceException("试卷保存失败,请联系管理员!");
        }
        // 删除掉旧题目试卷关联信息
        List<Long> newPaperQuesIds = bo.getPaperQuestionBo().stream()
                .map(BisPaperQuestionAddBo::getPaperQuestionId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        LambdaUpdateWrapper<BisPaperQuestions> wrapper = PlusWrappers.lambdaUpdate(BisPaperQuestions.class)
                .eq(BisPaperQuestions::getPaperId, bo.getPaperId())
                .notIn(BisPaperQuestions::getPaperQuestionId, newPaperQuesIds);
        paperQuestionMapper.delete(wrapper);

        // 修改原来的关联信息
        List<BisPaperQuestions> paperQuesList = new ArrayList<>();
        for (BisPaperQuestionAddBo question : bo.getPaperQuestionBo()) {
            BisPaperQuestions paperQuestions = new BisPaperQuestions();
            paperQuestions.setPaperQuestionId(question.getPaperQuestionId());
            paperQuestions.setQuestionOrder(question.getQuestionOrder());
            paperQuestions.setQuestionScore(question.getQuestionScore());
            paperQuesList.add(paperQuestions);
        }
        if(!paperQuestionMapper.insertOrUpdateBatch(paperQuesList)){
            throw new ServiceException("试卷题目信息保存失败,请联系管理员!");
        }

        // 返回试卷id，供前端回调 <试卷预览详情> 接口
        return bo.getPaperId();
    }


    /**
     * 删除试卷
     * @param quesIds
     * @return
     */
    @Override
    @Transactional
    public Boolean deletePaperQuestion(List<Long> quesIds) {
        // 删除试卷题目关联表中的数据
        LambdaUpdateWrapper<BisPaperQuestions> in = PlusWrappers.lambdaUpdate(BisPaperQuestions.class)
                .in(BisPaperQuestions::getPaperQuestionId, quesIds);
        paperQuestionMapper.delete(in);

        // 删除试卷表中的数据
        return baseMapper.deleteBatchIds(quesIds) > 0;
    }

    /**
     * 发布试卷
     * @param paperId
     * @return
     */
    @Override
    public Boolean publishPaper(Long paperId) {
        LambdaUpdateWrapper<BisPapers> wrapper = PlusWrappers.lambdaUpdate(BisPapers.class)
                .set(BisPapers::getStatus, PaperStatus.PUBLISHED)
                .eq(BisPapers::getPaperId, paperId);
        return baseMapper.update(wrapper) > 0;
    }

    @Override
    public Boolean recallPaper(Long paperId) {
        LambdaUpdateWrapper<BisPapers> wrapper = PlusWrappers.lambdaUpdate(BisPapers.class)
                .set(BisPapers::getStatus, PaperStatus.DRAFT)
                .eq(BisPapers::getPaperId, paperId);
        return baseMapper.update(wrapper) > 0;

    }

    @Override
    public Boolean archivePaper(Long paperId) {
        LambdaUpdateWrapper<BisPapers> wrapper = PlusWrappers.lambdaUpdate(BisPapers.class)
                .set(BisPapers::getStatus, PaperStatus.ARCHIVED)
                .eq(BisPapers::getPaperId, paperId);
        return baseMapper.update(wrapper) > 0;
    }

    @Override
    public void exportPaper(Long paperId, HttpServletResponse response) {


    }

    @Override
    public void exportWord(Long paperId, HttpServletResponse response) {

    }


    private MPJLambdaWrapperPlus<BisPapers> getPlusWrapper(){
        return new MPJLambdaWrapperPlus<>(BisPapers.class);
    }

    private LambdaQueryWrapperPlus<BisPapers> getWrapper(){
        return PlusWrappers.lambdaQuery(BisPapers.class);
    }


}
